<html><head>
    <meta http-equiv="content-type" content="text/html; charset=UTF-8"><title>UserGuide - Dynamic numbering of windows and gadgets using #PB_Any</title></head>
<body bgcolor="#FFFFDF" link="#009999" vlink="#006666" alink="#006666">
<font face="Arial" size="2"><p align="center"><b><font size="5">UserGuide - Dynamic numbering of windows and gadgets using #PB_Any</font></b></p>



If you抳e looked at the help articles for the <a href="../window/openwindow.html">OpenWindow</a> command 
or for any of the <a href="../gadget/index.html">gadget</a> creation commands (for example <a href="../gadget/buttongadget.html">ButtonGadget()</a>) 
or if you have experimented with the Form Designer tool, you may have noticed references to a 
special constant called <a href="../reference/purebasic_objects.html">#PB_Any</a>. In this article we抮e 
going to look into this a little further to find out why its so important. 
<br>
<br>
So far all of our examples have used a group of constants, an <a href="../reference/enumerations.html">enumeration</a>, 
to identify a single <a href="../window/index.html">window</a> and each <a href="../gadget/index.html">gadget</a> 
on that window. This is fine in the simple programs we抳e demonstrated so far but presents 
a problem in more complex programs �only one of each of these windows can exist at the 
same time. 
<br>
<br>
So what happens if a program needs to provide more than one copy of a window? Maybe to have 
several files open at once or possibly to provide several different views of the same file. 
<br>
<br>
This is where the special #PB_Any constant comes in. When this constant is used as the 
argument to the functions that support it, a unique reference number is automatically 
generated and returned as a result of the function. 
<br>
<br>
Providing we keep track of all these references we can use this to our advantage. 
Organising this is a little more complex than the examples we抳e seen so far �but the 
increased flexibility that it can provide makes this well worth the effort. 
<br>
<br>
This example program provides a window upon which a regular polygon is drawn in blue on a 
circumscribing grey circle. A combo box is provided to allow a selection of polygons to 
be drawn. A menu is provided to allow the creation of new windows or the closing of the 
current window. 
<br>
<br>
There are several things to notice about this program: 
 
<blockquote>



In the Enumerations section, note that there are only enumerations for the 
<a href="../menu/index.html">menu items</a>. These will be shared on all the windows �although 
each window will have its own menu bar. 
<br>
<br>
In the <a href="../reference/structures.html">Structures</a> section, note that the POLYGONWINDOW 
structure contains four integer values and so provides a place to store references 
for a menu bar, a label, a combo box and an image plot. 
<br>
<br>
In the Variables section note that in addition to the usual variables to receive event 
details, a <a href="../reference/newmap.html">map</a> called ActiveWindows is created using the 
POLYGONWINDOW structure previously defined. 
<br>
<br>
Look at the CreatePolygonWindow <a href="../reference/procedures.html">procedure</a>. <br>
When we create the window we capture the result of the <a href="../window/openwindow.html">OpenWindow()</a> function in a 
variable called ThisWindow. We then convert this to a string value and use this as 
the key for a new map entry. 
<br>
<br>
When we then create the <a href="../menu/createmenu.html">menu</a>, <a href="../gadget/textgadget.html">label</a>, 
<a href="../gadget/comboboxgadget.html">combo</a> and <a href="../gadget/imagegadget.html">image gadgets</a> 
on the new window the references returned by these functions are stored in the map too. 
<br>
<br>
Look at the ResizePolygonWindow procedure. <br>
Notice how the value of EventWindow is passed in from the event loop into this procedure. 
This value is then used to retrieve child control references from the map and these 
references are then used to <a href="../gadget/resizegadget.html">resize</a> the gadgets. 
<br>
<br>
Look at the DestroyPolygonWindow procedure. <br>
Here the child control references are removed from the map when a window is closed. 
If the map size reaches zero �there are no more open windows and DestroyPolygonWindow 
sets an event flag to tell the program to end. 
<br>
<br>
Start the program up. <br>
- Use the New Window menu item to open up two or three new polygon windows. <br>
- Use the combo box in each one to select a different shape �notice that each window 
works independently of all the others. <br>
- Resize some of the windows �notice that they can all be resized independently of 
each other and that the polygon resizes with the window too. <br>
</blockquote>





Finally, note that a <a href="../reference/newmap.html">map</a> isn抰 the only way to achieve this 
effect, a <a href="../reference/newlist.html">List</a> or an <a href="../reference/dim.html">Array</a> could 
be used to do the job too, if you prefer, although the code to implement these alternatives 
would need to be slightly different to that presented here because of the differences in 
the way those collections work. 
 
<br>
<pre><font face="Courier New, Courier, mono"size="2">  <font color="#006666">; Compiler Directives</font>
  <b><font color="#006666">EnableExplicit</font></b>
  
  <font color="#006666">; Constants</font>
  <b><font color="#006666">CompilerIf</font></b> <font color="#006666">Defined</font>(Blue, <font color="#924B72">#PB_Constant</font>) = <font color="#924B72">#False</font>
    <font color="#924B72">#Blue</font> = 16711680
    <font color="#924B72">#Gray</font> = 8421504
    <font color="#924B72">#White</font> = 16777215
  <b><font color="#006666">CompilerEndIf</font></b>
  
  <font color="#006666">;- Enumerations</font>
  <font color="#006666">; The menu commands will be the same on all the windows.</font>
  <b><font color="#006666">Enumeration</font></b>
    <font color="#924B72">#MenuNew</font>
    <font color="#924B72">#MenuClose</font>
  <b><font color="#006666">EndEnumeration</font></b>
  
  <font color="#006666">;- Structures</font>
  <font color="#006666">; This structure will hold references to the unique elements of a window.</font>
  <b><font color="#006666">Structure</font></b> POLYGONWINDOW
    Menu.i
    LabelSides.i
    ComboSides.i
    ImagePlot.i
  <b><font color="#006666">EndStructure</font></b>
  
  <font color="#006666">;- Variables</font>
  
  <font color="#006666">; This map uses the previously defined structure to hold references for all the open windows.</font>
  <b><font color="#006666">NewMap</font></b> <font color="#006666">ActiveWindows</font>.POLYGONWINDOW()
  
  <font color="#006666">; Event variables.</font>
  <b><font color="#006666">Define</font></b>.i Event, EventWindow, EventGadget, EventType, EventMenu, EventQuit
  <b><font color="#006666">Define</font></b>.s EventWindowKey
  
  <font color="#006666">; Implementation.</font>
  <b><font color="#006666">Procedure</font></b>.i <font color="#006666">CreatePolygonWindow</font>()
    <font color="#006666">; Creates a new window and gadgets, adding it and its child gadgets to the tracking map.</font>
    <b><font color="#006666">Shared</font></b> <font color="#006666">ActiveWindows</font>()
    <b><font color="#006666">Protected</font></b>.i ThisWindow
    <b><font color="#006666">Protected</font></b>.s ThisKey
    
    ThisWindow =<font color="#006666"> OpenWindow</font>(<font color="#924B72">#PB_Any</font>, 50, 50, 300, 300, "Polygon", <font color="#924B72">#PB_Window_SystemMenu</font> | <font color="#924B72">#PB_Window_SizeGadget</font> | <font color="#924B72">#PB_Window_MinimizeGadget</font> | <font color="#924B72">#PB_Window_TitleBar</font>)  
    
<font color="#006666">    WindowBounds</font>(ThisWindow, 250, 250, <font color="#924B72">#PB_Ignore</font>, <font color="#924B72">#PB_Ignore</font>)
    
    <b><font color="#006666">If</font></b> ThisWindow
      <font color="#006666">; Maps take a string value as key so convert the integer ThisWindow to a string.</font>
      ThisKey =<font color="#006666"> StrU</font>(ThisWindow)
      
      <font color="#006666">; Add a map element to hold the new gadget references.</font>
<font color="#006666">      AddMapElement</font>(<font color="#006666">ActiveWindows</font>(), ThisKey)
      
      <font color="#006666">; Create the menu bar.</font>
<font color="#006666">      ActiveWindows</font>(ThisKey)\Menu =<font color="#006666"> CreateMenu</font>(<font color="#924B72">#PB_Any</font>,<font color="#006666"> WindowID</font>(ThisWindow))
<font color="#006666">      MenuTitle</font>("Window")
<font color="#006666">      MenuItem</font>(<font color="#924B72">#MenuNew</font>, "New Window")
<font color="#006666">      MenuItem</font>(<font color="#924B72">#MenuClose</font>, "Close Window")
      
      <font color="#006666">; Create the child gadgets and store their references in the map.</font>
      <b><font color="#006666">With</font></b> <font color="#006666">ActiveWindows</font>()
        <font color="#006666">; A label for the combo.</font>
        \LabelSides =<font color="#006666"> TextGadget</font>(<font color="#924B72">#PB_Any</font>, 5, 5, 150, 20, "Number of Sides:")
        
        <font color="#006666">; The Sides combo.</font>
        \ComboSides =<font color="#006666"> ComboBoxGadget</font>(<font color="#924B72">#PB_Any</font>, 160, 5, 100, 25)
<font color="#006666">        AddGadgetItem</font>(\ComboSides, 0, "Triangle")
<font color="#006666">        AddGadgetItem</font>(\ComboSides, 1, "Diamond")
<font color="#006666">        AddGadgetItem</font>(\ComboSides, 2, "Pentagon")
<font color="#006666">        AddGadgetItem</font>(\ComboSides, 3, "Hexagon")
<font color="#006666">        AddGadgetItem</font>(\ComboSides, 4, "Heptagon")
<font color="#006666">        AddGadgetItem</font>(\ComboSides, 5, "Octagon")
<font color="#006666">        AddGadgetItem</font>(\ComboSides, 6, "Nonagon")
<font color="#006666">        AddGadgetItem</font>(\ComboSides, 7, "Decagon")
        
        <font color="#006666">; Select Triangle.</font>
<font color="#006666">        SetGadgetState</font>(\ComboSides, 0)
        
        <font color="#006666">; The visual image gadget on the window.</font>
        \ImagePlot =<font color="#006666"> ImageGadget</font>(<font color="#924B72">#PB_Any</font>, 5, 35, 290, 240, 0, <font color="#924B72">#PB_Image_Border</font>)
      <b><font color="#006666">EndWith</font></b>
    <b><font color="#006666">EndIf</font></b>
    
    <font color="#006666">; Return the reference to the new window.</font>
    <b><font color="#006666">ProcedureReturn</font></b> ThisWindow
  <b><font color="#006666">EndProcedure</font></b>
  
  <b><font color="#006666">Procedure</font></b> <font color="#006666">DestroyPolygonWindow</font>(Window.i)
    <font color="#006666">; Remove Window from the ActiveWindows map, close the window and set the quit flag, if appropriate.</font>
    <b><font color="#006666">Shared</font></b> EventQuit,<font color="#006666"> ActiveWindows</font>()
    <b><font color="#006666">Protected</font></b>.s ThisKey
    
    <font color="#006666">; Convert the integer Window to a string.</font>
    ThisKey =<font color="#006666"> StrU</font>(Window)
    
    <font color="#006666">; Delete the map entry.</font>
<font color="#006666">    DeleteMapElement</font>(<font color="#006666">ActiveWindows</font>(), ThisKey)
    
    <font color="#006666">; Close the window.</font>
<font color="#006666">    CloseWindow</font>(Window)
    
    <font color="#006666">; Check if there are still open windows.</font>
    <b><font color="#006666">If</font></b> <font color="#006666">MapSize</font>(<font color="#006666">ActiveWindows</font>()) = 0
      EventQuit = <font color="#924B72">#True</font>
    <b><font color="#006666">EndIf</font></b>
  <b><font color="#006666">EndProcedure</font></b>
  
  <b><font color="#006666">Procedure</font></b>.i <font color="#006666">ResizePolygonWindow</font>(Window.i)
    <font color="#006666">; Resize the child gadgets on Window.</font>
    <font color="#006666">; In practice only the ImageGadget needs to be resized in this example.</font>
    <b><font color="#006666">Shared</font></b> <font color="#006666">ActiveWindows</font>()
    <b><font color="#006666">Protected</font></b>.i ThisImage
    <b><font color="#006666">Protected</font></b>.i X, Y, W, H
    <b><font color="#006666">Protected</font></b>.s ThisKey
    
    <font color="#006666">; Obtain references to the affected gadgets from the map.</font>
    ThisKey =<font color="#006666"> StrU</font>(Window)
    ThisImage =<font color="#006666"> ActiveWindows</font>(ThisKey)\ImagePlot
    
    <font color="#006666">; Resize gadgets.</font>
    W =<font color="#006666"> WindowWidth</font>(Window) - 15
    H =<font color="#006666"> WindowHeight</font>(Window) - 70
<font color="#006666">    ResizeGadget</font>(ThisImage, <font color="#924B72">#PB_Ignore</font>, <font color="#924B72">#PB_Ignore</font>, W, H)
  <b><font color="#006666">EndProcedure</font></b>
  
  <b><font color="#006666">Procedure</font></b> <font color="#006666">PlotPolygon</font>(Window.i)
    <font color="#006666">; Draw the polygon image and transfer it to the image gadget.</font>
    <b><font color="#006666">Shared</font></b> <font color="#006666">ActiveWindows</font>()
    <b><font color="#006666">Protected</font></b>.f Radius, OriginX, OriginY, StartX, StartY, EndX, EndY
    <b><font color="#006666">Protected</font></b>.i Sides, Vertex, Width, Height, ThisCombo, ThisImage, ThisPlot
    <b><font color="#006666">Protected</font></b>.s ThisKey
    
    <font color="#006666">; Obtain references to the affected gadgets from the map.</font>
    ThisKey =<font color="#006666"> StrU</font>(Window)
    ThisCombo =<font color="#006666"> ActiveWindows</font>(ThisKey)\ComboSides
    ThisImage =<font color="#006666"> ActiveWindows</font>(ThisKey)\ImagePlot
    
    <font color="#006666">; Calculate dimensions and origin.</font>
    Sides =<font color="#006666"> GetGadgetState</font>(ThisCombo) + 3
    Width =<font color="#006666"> GadgetWidth</font>(ThisImage) - 4
    Height =<font color="#006666"> GadgetHeight</font>(ThisImage) - 4
    OriginX = Width/2
    OriginY = Height/2
    <b><font color="#006666">If</font></b> Width &lt; Height
      Radius = OriginX - 50
    <b><font color="#006666">Else</font></b>
      Radius = OriginY - 50
    <b><font color="#006666">EndIf</font></b>
    
    <font color="#006666">; Create a new image.</font>
    ThisPlot =<font color="#006666"> CreateImage</font>(<font color="#924B72">#PB_Any</font>, Width, Height)
<font color="#006666">    StartDrawing</font>(<font color="#006666">ImageOutput</font>(ThisPlot))
    
    <font color="#006666">; Draw a white background.</font>
<font color="#006666">    Box</font>(0, 0, Width, Height, <font color="#924B72">#White</font>)
    
    <font color="#006666">; Draw a gray circumscribing circle.</font>
<font color="#006666">    Circle</font>(OriginX, OriginY, Radius, <font color="#924B72">#Gray</font>)
    
    <font color="#006666">; Draw the polygon.</font>
    <b><font color="#006666">For</font></b> Vertex = 0 <b><font color="#006666">To</font></b> Sides
      
      <font color="#006666">; Calculate side start point.</font>
      StartX =  OriginX + (Radius *<font color="#006666"> Cos</font>(2 * <font color="#924B72">#PI</font> * Vertex/Sides))
      StartY = OriginY + (Radius *<font color="#006666"> Sin</font>(2 * <font color="#924B72">#PI</font> * Vertex/Sides)) 
      
      <font color="#006666">; and end point.</font>
      EndX = OriginX + (Radius *<font color="#006666"> Cos</font>(2 * <font color="#924B72">#PI</font> * (Vertex + 1)/Sides))
      EndY = OriginY + (Radius *<font color="#006666"> Sin</font>(2 * <font color="#924B72">#PI</font> * (Vertex + 1)/Sides))
      
      <font color="#006666">; Draw the side in blue.</font>
<font color="#006666">      LineXY</font>(StartX, StartY, EndX, EndY, <font color="#924B72">#Blue</font>)
      
    <b><font color="#006666">Next</font></b> Vertex
    
    <font color="#006666">; Fill the polygon in blue</font>
<font color="#006666">    FillArea</font>(OriginX, OriginY, <font color="#924B72">#Blue</font>, <font color="#924B72">#Blue</font>)
    
<font color="#006666">    StopDrawing</font>()
    
    <font color="#006666">; Transfer the image contents to the visible gadget.</font>
<font color="#006666">    SetGadgetState</font>(ThisImage,<font color="#006666"> ImageID</font>(ThisPlot))
    
    <font color="#006666">; Destroy the temporary image.</font>
<font color="#006666">    FreeImage</font>(ThisPlot)
  <b><font color="#006666">EndProcedure</font></b>
  
  <font color="#006666">;- Main</font>
  
  <font color="#006666">; Create the first window.</font>
  EventWindow =<font color="#006666"> CreatePolygonWindow</font>()
<font color="#006666">  ResizePolygonWindow</font>(EventWindow)
<font color="#006666">  PlotPolygon</font>(EventWindow)
  
  <font color="#006666">;- Event loop</font>
  <b><font color="#006666">Repeat</font></b>
    Event =<font color="#006666"> WaitWindowEvent</font>()
    EventWindow =<font color="#006666"> EventWindow</font>()
    EventWindowKey =<font color="#006666"> StrU</font>(EventWindow)
    EventGadget =<font color="#006666"> EventGadget</font>()
    EventType =<font color="#006666"> EventType</font>()
    EventMenu =<font color="#006666"> EventMenu</font>()
    
    <b><font color="#006666">Select</font></b> Event
      <b><font color="#006666">Case</font></b> <font color="#924B72">#PB_Event_Gadget</font>
        <font color="#006666">; A gadget event has occurred.</font>
        <b><font color="#006666">If</font></b> EventGadget =<font color="#006666"> ActiveWindows</font>(EventWindowKey)\LabelSides
          <font color="#006666">; Do nothing.</font>
          
        <b><font color="#006666">ElseIf</font></b> EventGadget =<font color="#006666"> ActiveWindows</font>(EventWindowKey)\ComboSides
          <font color="#006666">; If the combo box changes, redraw the image.</font>
<font color="#006666">          PlotPolygon</font>(EventWindow)
          
          <font color="#006666">; Update the windows title to reflect the new shape.</font>
<font color="#006666">          SetWindowTitle</font>(EventWindow,<font color="#006666"> GetGadgetText</font>(<font color="#006666">ActiveWindows</font>(EventWindowKey)\ComboSides))
          
        <b><font color="#006666">ElseIf</font></b> EventGadget =<font color="#006666"> ActiveWindows</font>(EventWindowKey)\ImagePlot
          <font color="#006666">; Do nothing.</font>
          
        <b><font color="#006666">EndIf</font></b>
        
      <b><font color="#006666">Case</font></b> <font color="#924B72">#PB_Event_Menu</font>
        <font color="#006666">; A menu event has occurred.</font>
        <b><font color="#006666">If</font></b> EventMenu = <font color="#924B72">#MenuNew</font>
          EventWindow =<font color="#006666"> CreatePolygonWindow</font>()
<font color="#006666">          ResizePolygonWindow</font>(EventWindow)
<font color="#006666">          PlotPolygon</font>(EventWindow)
          
        <b><font color="#006666">ElseIf</font></b> EventMenu = <font color="#924B72">#MenuClose</font>
<font color="#006666">          DestroyPolygonWindow</font>(EventWindow)
          
        <b><font color="#006666">EndIf</font></b>
        
      <b><font color="#006666">Case</font></b> <font color="#924B72">#PB_Event_Repaint</font>
        <font color="#006666">; A window's content has been invalidated.</font>
<font color="#006666">        PlotPolygon</font>(EventWindow)
        
      <b><font color="#006666">Case</font></b> <font color="#924B72">#PB_Event_SizeWindow</font>
        <font color="#006666">; A window has been resized.</font>
<font color="#006666">        ResizePolygonWindow</font>(EventWindow)
<font color="#006666">        PlotPolygon</font>(EventWindow)
        
      <b><font color="#006666">Case</font></b> <font color="#924B72">#PB_Event_CloseWindow</font>
        <font color="#006666">; A window has been closed.</font>
<font color="#006666">        DestroyPolygonWindow</font>(EventWindow)
        
    <b><font color="#006666">EndSelect</font></b>
    
  <b><font color="#006666">Until</font></b> EventQuit = <font color="#924B72">#True</font>
</font></pre>

<p><b>UserGuide Navigation</b></p><blockquote>

<a href="../reference/ug_memory.html">&lt; Previous: Memory access</a> | <a href="../reference/ug_overview.html">Overview</a> | <a href="../reference/ug_pb_any2.html">Next: Managing multiple windows &gt;</a> 
</body></html>